/**
 * @func 手写Promise-class版本
 * @param {function} executor 
 */
class Promise {
    // 构造方法
    constructor(executor){
        // 添加属性
        this.PromiseState = 'pending';
        this.PromiseResult = null;
        this.callbacks=[];
        // 保存实例对象的 this 值
        const self = this;
        // resolve 函数
        function resolve(data){
            // 判断状态  状态只能修改一次
            if(self.PromiseState!=='pending') return;
            // 1. 修改对象状态 
            self.PromiseState = 'fulfilled';
            // 2. 设置对象结果值
            self.PromiseResult = data;
            // 异步执行
            setTimeout(() => {
                // 调用成功的回调函数
                self.callbacks.forEach(item =>{
                    item.onResolved(data);
                });
            }) 
        }
        // ewject 函数
        function reject(data){
            // 判断状态
            if(self.PromiseState!=='pending') return;
            // 1. 修改对象状态 
            self.PromiseState = 'rejected';
            // 2. 设置对象结果值
            self.PromiseResult = data;
            setTimeout(() => {
                // 调用失败的回调函数
                self.callbacks.forEach(item =>{
                    item.onRejected(data);
                });
            })
        }

        try{
            // 同步调用 [执行器函数]
            executor(resolve,reject);
        }catch(e) {
            reject(e);
        }
    }

    // then 方法封装
    then(onResolved,onRejected) {
        const self = this;
        // 判断回调函数参数 不传参数=默认参数
        if(typeof onRejected !== 'function'){
            onRejected = reason => {
                throw reason;
            }
        }
        if(typeof onResolved !== 'function'){
            onResolved = value => value;
        }
        return new Promise((resolve,reject) =>{
            // 封装函数
            const self=this;
            function callback(type){
                try{
                    let result=type(self.PromiseResult);
                     if(result instanceof Promise){
                         result.then(v=>{
                             resolve(v);
                         },r=>{
                             reject(r);
                         })
                     } else {
                         resolve(result);
                     }
                 }catch(e){
                     reject(e);
                 } 
            }
             // 调用回调函数
            if(this.PromiseState==='fulfilled'){
                // 异步执行
                setTimeout(()=>{
                     callback(onResolved);
                })
            }
            if(this.PromiseState==='rejected'){
               // 异步执行
                setTimeout(()=>{
                   callback(onRejected);
               })
            }
            if(this.PromiseState==='pending'){
                // 保存回调函数
                this.callbacks.push( {
                    onResolved:function(){
                       callback(onResolved);
                    },
                    onRejected:function(){
                       callback(onRejected);
                    }
                })
            }
        })
    }

    // catch 方法
    catch(onRejected) {
         return this.then(undefined,onRejected);
    }

    // resolve 方法
    // 它是属于Promise函数对象的，不是属于实例对象的
    static resolve(value) {
          // 返回 Promise 对象
        return new Promise((resolve,reject) =>{
            if(value instanceof Promise){
                value.then(v=>{
                    resolve(v);
                },r=>{
                    reject(r);
                })
            } else {
                // 状态设置为成功
                resolve(value);
            }
        })
    }

    // 添加 reject 方法
    static reject(reason) {
        return new Promise((resolve,reject) => {
            reject(reason);
        })
    }

    // 添加 all 方法
    static all(promises) {
         // 返回结果为 Promise 对象
        return new Promise((resolve,reject) =>{
            // 声明变量
            let count = 0;
            let arr = [];
            // 遍历
            for(let i=0;i<promises.length;i++){
                // 用then,保证异步任务顺序也能一致
                promises[i].then(v => {
                    // 得到对象的状态是成功
                    // 每个 promise 对象都成功
                    count++;
                    // 将当前 promise 对象成功的结果 存入到数组中
                    // push 不能保证顺序
                    arr[i] =v;
                    if(count === promises.length){
                        resolve(arr)
                    }
                },r => {
                    reject(r);
                });
            }
        });
    }

    // race 方法
    static race(promises) {
         return new Promise((resolve,reject) => {
            for(let i=0;i<promises.length;i++) {
                // 使用 then，谁先改变状态，谁就决定结果
                promises[i].then(v => {
                    // 修改返回对象的状态 [成功]
                    resolve(v);
                },r =>{
                    // 修改返回对象的状态 [失败]
                    reject(r);
                })
            }
        })
    }
}


